﻿using System;
using System.Text;

namespace yunio.websocket
{
    using System.Collections.Generic;
    internal partial class helper
    {
        internal const string queryTag = "?";
        internal const string queryConcatChar = "&";
        internal const string queryEqChar = "=";
        // 安全字符集合（RFC 3986 定义的 unreserved 字符）
        internal const string SafeChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
        public static void uri_add_param(ref string uri, YunioParam param)
        {
            if (!uri.Contains(queryTag)) uri += queryTag;
            if (!uri.EndsWith(queryConcatChar) && !uri.EndsWith(queryTag)) uri += queryConcatChar;
            foreach (var kv in param.LoopParam())
            {
                uri += $"{kv.Key}{queryEqChar}{uri_encode(kv.Value)}{queryConcatChar}";
            }
            uri = uri.TrimEnd(queryConcatChar[0]);
        }
        public static string uri_encode(string input)
        {
            if (string.IsNullOrEmpty(input)) return string.Empty;

            var sb = new StringBuilder();
            byte[] bytes = Encoding.UTF8.GetBytes(input);

            foreach (byte b in bytes)
                if (SafeChars.IndexOf((char)b) >= 0) sb.Append((char)b);
                else if (b == 0x20) sb.Append('+');
                else sb.AppendFormat("%{0:X2}", b);

            return sb.ToString();
        }
        public static string uri_decode(string input)
        {
            if (string.IsNullOrEmpty(input))
                return string.Empty;

            List<byte> byteList = new List<byte>();
            int length = input.Length;
            int index = 0;

            while (index < length)
            {
                char currentChar = input[index];
                if (currentChar == '+')
                {
                    byteList.Add((byte)' ');
                    index++;
                }
                else if (currentChar == '%')
                {
                    if (index + 2 < length)
                    {
                        char hex1 = input[index + 1];
                        char hex2 = input[index + 2];
                        if (IsValidHexChar(hex1) && IsValidHexChar(hex2))
                        {
                            byte decodedByte = (byte)((HexCharToInt(hex1) << 4) | HexCharToInt(hex2));
                            byteList.Add(decodedByte);
                            index += 3;
                            continue;
                        }
                    }
                    byteList.Add((byte)currentChar);
                    index++;
                }
                else
                {
                    byteList.Add((byte)currentChar);
                    index++;
                }
            }

            return Encoding.UTF8.GetString(byteList.ToArray());
        }

        private static bool IsValidHexChar(char c)
        {
            return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
        }
        private static int HexCharToInt(char c)
        {
            if (c >= '0' && c <= '9')
                return c - '0';
            if (c >= 'a' && c <= 'f')
                return 10 + c - 'a';
            if (c >= 'A' && c <= 'F')
                return 10 + c - 'A';
            return 0;
        }
    }
}
